package com.yanyeori.utilscollection.jira;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.yanyeori.framework.jira.jiraclient.Field;
import com.yanyeori.framework.jira.jiraclient.Issue;
import com.yanyeori.framework.jira.jiraclient.JiraClient;
import com.yanyeori.framework.jira.jiraclient.JiraException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * jira 服务
 *
 * @author chenkuan
 * @since 2023/2/23
 */
@Slf4j
@Service
public class JiraService {

    //所属项目
    @Value("${jira.project:SCBUG}")
    private String project;

    //issue类型
    @Value("${jira.issueType:缺陷}")
    private String issueType;

    @Autowired
    private JiraClient jiraClient;

    /**
     * 创建issue
     *
     * @param issueBO 参数
     * @return Issue
     */
    public Issue createIssue(IssueBO issueBO) throws JiraException {
        //查询项目、问题类型字段配置
//        List<JiraFieldConfig> fieldConfigs = jiraFieldConfigService.listByProjectAndIssueType(project, issueType);
        List<JiraFieldConfig> fieldConfigs = new ArrayList<>();
        if (CollUtil.isEmpty(fieldConfigs)) {
            throw new RuntimeException(StrUtil.format("项目:{}, 问题类型:{} 未配置字段", project, issueType));
        }

        Issue.FluentCreate issue = jiraClient.createIssue(project, issueType);
        for (JiraFieldConfig field : fieldConfigs) {
            Object value = StrUtil.isEmpty(field.getBeanField()) ? null : BeanUtil.getFieldValue(issueBO, field.getBeanField());
            //未从参数bean中取到参数值，则使用默认值
            String fieldDefault = field.getFieldDefault();
            switch (field.getFieldType()) {
                case STR:
                    if (ObjectUtil.isEmpty(value) && StrUtil.isNotEmpty(fieldDefault)) {
                        value = fieldDefault;
                    }
                    if (ObjectUtil.isNotEmpty(value)) {
                        issue.field(field.getFieldCode(), value);
                    }
                    break;
                case STR_TAG:
                    if (ObjectUtil.isEmpty(value) && StrUtil.isNotEmpty(fieldDefault)) {
                        value = StrUtil.split(fieldDefault, StrUtil.COMMA);
                    }
                    if (ObjectUtil.isNotEmpty(value)) {
                        issue.field(field.getFieldCode(), value);
                    }
                    break;
                case SEL_SIN:
                    if (ObjectUtil.isEmpty(value) && StrUtil.isNotEmpty(fieldDefault)) {
                        value = fieldDefault;
                    }
                    if (ObjectUtil.isNotEmpty(value)) {
                        issue.field(field.getFieldCode(), Field.valueByValue(String.valueOf(value)));
                    }
                    break;
                case SEL_MUL:
                    if (ObjectUtil.isEmpty(value) && StrUtil.isNotEmpty(fieldDefault)) {
                        value = StrUtil.split(fieldDefault, StrUtil.COMMA);
                    }
                    if (ObjectUtil.isNotEmpty(value) && value instanceof List) {
                        issue.field(field.getFieldCode(), ((List<String>) value).stream().map(Field::valueByValue).collect(Collectors.toList()));
                    }
                    break;
                case DATE:
                    if ((ObjectUtil.isEmpty(value) || !(value instanceof Date)) && StrUtil.isNotEmpty(fieldDefault)) {
                        try {
                            value = DateUtil.parse(fieldDefault);
                        } catch (Exception e) {
                            log.warn("field: {}, fieldDefault: {}, convert error", JSONUtil.toJsonStr(field), fieldDefault);
                            break;
                        }
                    }
                    issue.field(field.getFieldCode(), ObjectUtil.isEmpty(value) ? new Date() : value);
                    break;
            }
        }
        return issue.execute();
    }

    /**
     * 查询issue
     *
     * @param issueKey issueKey
     * @return Issue
     */
    public Issue getIssue(String issueKey) throws JiraException {
        return jiraClient.getIssue(issueKey);
    }

    /**
     * 批量查询issue
     *
     * @param issueKeys      issueKey列表
     * @param includedFields 查询字段
     * @return Map<String, Issue>
     */
    public Map<String, Issue> listIssue(List<String> issueKeys, String... includedFields) throws JiraException {
        if (CollUtil.isEmpty(issueKeys)) {
            return new HashMap<>(0);
        }
        Set<String> issueKeySet = issueKeys.stream().map(String::toLowerCase).collect(Collectors.toSet());
        String jql = StrUtil.format("issueKey in ({})", StrUtil.join(StrUtil.COMMA, issueKeySet));
        String includedField = ArrayUtil.isNotEmpty(includedFields) ? StrUtil.join(StrUtil.COMMA, includedFields) : null;
        Issue.SearchResult result = jiraClient.searchIssues(jql, includedField, issueKeySet.size());
        List<Issue> issues = result.issues;
        if (CollUtil.isEmpty(issues)) {
            return new HashMap<>(0);
        }
        return issues.stream().collect(Collectors.toMap(Issue::getKey, x -> x));
    }

    /**
     * 批量查询issue状态
     *
     * @param issueKeys issueKey列表
     * @return Map<String, String>
     */
    public Map<String, String> listIssueStatus(List<String> issueKeys) throws JiraException {
        Map<String, Issue> issueMap = listIssue(issueKeys, "status");
        if (MapUtil.isEmpty(issueMap)) {
            return new HashMap<>(0);
        }
        return issueMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, x -> x.getValue().getStatus().getName()));
    }
}
